﻿using Microsoft.Xna.Framework;

namespace Babylon.Toolbox
{
    public partial class SceneObject
    {
        Vector3 position;
        Vector3 rotate;
        Vector3 scale = new Vector3(1, 1, 1);
        Matrix? userWorldMatrix;
        Matrix world = Matrix.Identity;

        public Vector3 Position
        {
            get { return position; }
            set
            {
                if (position == value)
                    return;

                position = value;

                UpdateWorldMatrix();
                RaisePropertyChanged(() => Position);
            }
        }

        public Vector3 Scale
        {
            get { return scale; }
            set
            {
                if (scale == value)
                    return;

                scale = value;

                UpdateWorldMatrix();
                RaisePropertyChanged(() => Scale);
            }
        }

        public Vector3 Rotate
        {
            get { return rotate; }
            set
            {
                if (rotate == value)
                    return;

                rotate = value;

                UpdateWorldMatrix();
                RaisePropertyChanged(() => Rotate);
            }
        }

        public float X
        {
            get { return position.X; }
            set
            {
                if (position.X == value)
                    return;

                position.X = value;

                RaisePropertyChanged(()=>X);
                UpdateWorldMatrix();
            }
        }

        public float Y
        {
            get { return position.Y; }
            set
            {
                if (position.Y == value)
                    return;

                position.Y = value;

                RaisePropertyChanged(() => Y);
                UpdateWorldMatrix();
            }
        }

        public float Z
        {
            get { return position.Z; }
            set
            {
                if (position.Z == value)
                    return;

                position.Z = value;

                RaisePropertyChanged(() => Z);
                UpdateWorldMatrix();
            }
        }

        public float RotateX
        {
            get { return rotate.X; }
            set
            {
                if (rotate.X == value)
                    return;

                rotate.X = value;

                RaisePropertyChanged(() => RotateX);
                UpdateWorldMatrix();
            }
        }

        public float RotateY
        {
            get { return rotate.Y; }
            set
            {
                if (rotate.Y == value)
                    return;

                rotate.Y = value;

                RaisePropertyChanged(() => RotateY);
                UpdateWorldMatrix();
            }
        }

        public float RotateZ
        {
            get { return rotate.Z; }
            set
            {
                if (rotate.Z == value)
                    return;

                rotate.X = value;

                RaisePropertyChanged(() => RotateZ);
                UpdateWorldMatrix();
            }
        }

        public float ScaleX
        {
            get { return scale.X; }
            set
            {
                if (scale.X == value)
                    return;

                scale.X = value;

                RaisePropertyChanged(() => ScaleX);
                UpdateWorldMatrix();
            }
        }

        public float ScaleY
        {
            get { return scale.Y; }
            set
            {
                if (scale.Y == value)
                    return;

                scale.Y = value;

                RaisePropertyChanged(() => ScaleY);
                UpdateWorldMatrix();
            }
        }

        public float ScaleZ
        {
            get { return scale.Z; }
            set
            {
                if (scale.Z == value)
                    return;

                scale.X = value;

                RaisePropertyChanged(() => ScaleZ);
                UpdateWorldMatrix();
            }
        }

        void UpdateWorldMatrix()
        {
            world = Matrix.CreateScale(scale) * Matrix.CreateRotationY(rotate.Y) * Matrix.CreateRotationX(rotate.X) * Matrix.CreateRotationZ(rotate.Z) * Matrix.CreateTranslation(position);
        }
             
        public Matrix World
        {
            get
            {
                if (userWorldMatrix.HasValue)
                    return userWorldMatrix.Value;

                return world;
            }
            set { userWorldMatrix = value; }
        }
    }
}
